package com.sunday.common.trace.zipkin.study.spring.thread;

import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.propagation.CurrentTraceContext;
import brave.propagation.TraceContext;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static brave.Span.Kind.CONSUMER;


@Slf4j
@RestController
@RequestMapping("/thread/pool")
@RequiredArgsConstructor
public class ThreadPoolApi {

    @Resource(name = "threadPool")
    private ThreadPoolTaskExecutor threadPool;

    @Resource(name = "threadPool2")
    private ThreadPoolTaskExecutor threadPool2;

    private final Tracing tracing;

    @GetMapping("/save")
    public String save() {

        log.info("start=================================================");


        tracing();

        normal();

        newFixedThreadPool();


        log.info("end=================================================");

        return LocalDateTime.now().toString();
    }

    protected void newFixedThreadPool() {
        ExecutorService exec = Executors.newFixedThreadPool(10);
        exec = Tracing.current().currentTraceContext().executorService(exec);

        exec.execute(() -> {
            log.info("[newFixedThreadPool][execute] brave init ============");
        });

        exec.submit(() -> {
            log.info("[newFixedThreadPool][submit] brave init ===========");
            return null;
        });
    }

    protected void normal() {
        threadPool2.execute(() -> {
            log.info("[normal][execute] brave init ============");
        });

        threadPool2.submit(() -> {
            log.info("[normal][submit] brave init ===========");
            return null;
        });
    }

    protected void tracing() {

        Tracer tracer = tracing.tracer();
        CurrentTraceContext currentTraceContext = tracing.currentTraceContext();
        TraceContext maybeParent = currentTraceContext.get();

        threadPool.execute(() -> {
            Span span = tracer.newChild(maybeParent);
            Tracer.SpanInScope spanInScope = tracer.withSpanInScope(span);
            try {
                span.kind(CONSUMER).name("execute").start();
                log.info("[tracing][execute] brave init ============");
            } finally {
                span.finish();
                spanInScope.close();
            }
//            log.info("[tracing][execute] brave init ============");
        });

        threadPool.submit(() -> {
            Span span = tracer.newChild(maybeParent);
            Tracer.SpanInScope spanInScope = tracer.withSpanInScope(span);
            try {
                span.kind(CONSUMER).name("submit").start();
                log.info("[tracing][submit] brave init ===========");
            } finally {
                span.finish();
                spanInScope.close();
            }
//            log.info("[tracing][submit] brave init ===========");
            return null;
        });
    }

}